package org.refresh.tests;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.refresh.injectors.XMLInjector;
import org.refresh.injectors.XMLInjector.UnknownAnnotationTypeException;
import org.refresh.injectors.xml.ForEachAnnotation;
import org.refresh.injectors.xml.InjectionException;
import org.refresh.injectors.xml.InsertAnnotation;
import org.refresh.injectors.xml.ReplaceAnnotation;
import org.refresh.util.ArgumentsFormatException;

/******************************************************************************
 * Copyright (c) 2005, 2006 Jules White.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Jules White - initial API and implementation 
 ****************************************************************************/
public class XmlInjectorTest extends TestCase {

	public void testInsert(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](insert){<b></b>}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new InsertAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b></b></a>",injector.inject(enabled,bindings, conf));
		
//		HashMap<String, Map<String,List<String>>> traces = new HashMap<String, Map<String,List<String>>>();
//		HashMap<String, List<String>> footrace = new HashMap<String, List<String>>();
//		List<String> binders = new ArrayList<String>();
//		binders.add("foo.child");
//		footrace.put("id", binders);
//		traces.put("foo", footrace);
//		injector.setEnableTracing(true);
//		injector.setBindingsTraceInformation(traces);
//		System.out.println(injector.inject(enabled,bindings, conf));
	}
	
	public void testReplaceAttribute(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](replace[@id=${id}]){--><b id=\"wrong\"></b><!--}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ReplaceAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"some_id\"></b></a>",injector.inject(enabled,bindings, conf));
		
		HashMap<String, Map<String,List<String>>> traces = new HashMap<String, Map<String,List<String>>>();
		HashMap<String, List<String>> footrace = new HashMap<String, List<String>>();
		List<String> binders = new ArrayList<String>();
		binders.add("foo.child");
		footrace.put("id", binders);
		traces.put("foo", footrace);
		injector.setEnableTracing(true);
		injector.setBindingsTraceInformation(traces);
		System.out.println(injector.inject(enabled,bindings, conf));
	}
	
	public void testReplaceValue(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](replace[#value=foobar]){--><b id=\"a\">asdfa</b><!--}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ReplaceAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"a\">foobar</b></a>",injector.inject(enabled,bindings, conf));
	}
	
	public void testReplaceValueUsingWith(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](replace[#value=${with}]){--><b id=\"a\">asdfa</b><!--} with {<c><d/></c>}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ReplaceAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"a\"><c><d/></c></b></a>",injector.inject(enabled,bindings, conf));
	}
	
	public void testReplaceWith(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](replace){--><b id=\"a\">asdfa</b><!--} with {<c><d/></c>}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ReplaceAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><c><d/></c></a>",injector.inject(enabled,bindings, conf));
	}
	
	public void testReplaceMix(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](replace[#value=${with}; @id=${id}; @size=2]){--><b id=\"a\" size=\"3\">asdfa</b><!--} with {<c><d/></c>}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ReplaceAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"some_id\" size=\"2\"><c><d/></c></b></a>",injector.inject(enabled,bindings, conf));
	}
	
	public void testReplaceMixWithMultipleSources(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		enabled.put("bar", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		
		foobinds.put("id", "some_id");
		bindings.put("foo", foobinds);
		
		HashMap<String, Object> barbinds = new HashMap<String, Object>();
		barbinds.put("foo.ior","234231432434");
		bindings.put("bar",barbinds);
		HashMap attrs = new HashMap();
		attrs.put("a", "bb");
		attrs.put("c", "dd");
		barbinds.put("foo.attrs",attrs);
		
		String conf = "<a><!--feature[foo](replace[#value=${with}; @id=${id}; @ior=${ior}; @size=2]){--><b id=\"a\" ior=\"11111111\" size=\"3\">asdfa</b><!--} with {<c><d/></c>}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ReplaceAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"some_id\" ior=\"234231432434\" size=\"2\"><c><d/></c></b></a>",injector.inject(enabled,bindings, conf));
		
//		injector.setEnableTracing(true);
//		System.out.println(injector.inject(enabled,bindings, conf));
	}
	
	public void testForEachWithSimpleList(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		ArrayList mylist = new ArrayList();
		mylist.add("foo");
		mylist.add("bar");
		foobinds.put("mylist",mylist);
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](for-each[list=mylist]){--><b id=\"${value}\"/><!--}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ForEachAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"foo\"/><b id=\"bar\"/></a>",injector.inject(enabled,bindings, conf));
	}
	
	public void testForEachWithMapList(){
		HashMap<String,Boolean> enabled = new HashMap<String, Boolean>();
		enabled.put("foo", true);
		HashMap<String, Map> bindings = new HashMap<String, Map>();
		HashMap<String, Object> foobinds = new HashMap<String, Object>();
		ArrayList mylist = new ArrayList();
		Map attrs = new HashMap();
		attrs.put("id", "foo");
		attrs.put("size","1");
		mylist.add(attrs);
		attrs = new HashMap();
		attrs.put("id", "bar");
		attrs.put("size", "2");
		mylist.add(attrs);
		foobinds.put("mylist",mylist);
		bindings.put("foo", foobinds);
		String conf = "<a><!--feature[foo](for-each[list=mylist]){--><b id=\"${id}\" size=\"${size}\"/><!--}--></a>";
		XMLInjector injector = new XMLInjector();
		injector.addAnnotationHandler(new ForEachAnnotation());
		injector.setEnableTracing(false);
		assertEquals("<a><b id=\"foo\" size=\"1\"/><b id=\"bar\" size=\"2\"/></a>",injector.inject(enabled,bindings, conf));
		

//		HashMap<String, Map<String,List<String>>> traces = new HashMap<String, Map<String,List<String>>>();
//		HashMap<String, List<String>> footrace = new HashMap<String, List<String>>();
//		List<String> binders = new ArrayList<String>();
//		binders.add("foo.child");
//		binders.add("foo.child2");
//		footrace.put("mylist", binders);
//		traces.put("foo", footrace);
//		injector.setEnableTracing(true);
//		injector.setBindingsTraceInformation(traces);
//		System.out.println(injector.inject(enabled,bindings, conf));
	}
	
	public void testInvalidAnnotation(){
		String conf = "<a><!--feature[foo](non-existant-annotation[a=b]){--><b></b><!--} with {my_with_stmt}--></a>";
		XMLInjector injector = new XMLInjector();
		try{
			injector.inject(new HashMap<String, Boolean>(), new HashMap<String, Map>(), conf);
			fail("The XMLInjector should have thrown an UnknownAnnotationTypeException");
		}
		catch (InjectionException e) {
			assertEquals(UnknownAnnotationTypeException.class, e.getCause().getClass());
		}
	}
	
	public void testInvalidArgs(){
		String conf = "<a><!--feature[foo](remove[a=]){<b></b>}--></a>";
		XMLInjector injector = new XMLInjector();
		try{
			injector.inject(new HashMap<String, Boolean>(), new HashMap<String, Map>(), conf);
			fail("The XMLInjector should have thrown an ArgumentsFormatException");
		}
		catch (InjectionException e) {
			assertEquals(ArgumentsFormatException.class, e.getCause().getClass());
		}
	}
	
}
